package com.pencilisland.pay.mgt.console.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.pencilisland.pay.mgt.console.entity.SysOrg;
import com.pencilisland.pay.mgt.console.entity.SysRole;
import com.pencilisland.pay.mgt.console.entity.SysRoleObj;
import com.pencilisland.pay.mgt.console.entity.SysRole_;
import com.pencilisland.pay.mgt.console.entity.SysUser;
import com.pencilisland.pay.mgt.console.repository.RoleObjRepository;
import com.pencilisland.pay.mgt.console.repository.RoleRepository;
import com.pencilisland.pay.mgt.console.service.RoleService;
import com.pencilisland.pay.mgt.util.G;

@Component
public class RoleServiceImpl implements RoleService {

	@Autowired
	RoleRepository roleRepo;
	@Autowired
	RoleObjRepository roleObjRepo;

	@Override
	public Page<SysRole> roleList(final String cretiria, int start, int limit) {

		Specification<SysRole> spec = new Specification<SysRole>() {

			@Override
			public Predicate toPredicate(Root<SysRole> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				if (!StringUtils.isEmpty(cretiria)) {
					list.add(cb.or(cb.like(root.get(SysRole_.roleKey), "%" + cretiria + "%"),
							cb.like(root.get(SysRole_.roleKey), "%" + cretiria + "%")));
				}
				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}
		};

		Sort sort = new Sort(new Order(Sort.Direction.ASC, SysRole_.roleKey.getName()));

		Pageable pageable = new PageRequest(start/limit, limit, sort);

		return roleRepo.findAll(spec, pageable);

	}

	@Override
	public List<SysRoleObj> roleObjList(Long roleId) {
		if (roleId == null)
			return new ArrayList<SysRoleObj>();
		return roleObjRepo.findByRoleIdOrderByObjTypeAsc(roleId);
	}

	@Override
	public SysRole save(SysRole role) {
		return roleRepo.save(role);
	}

	@Override
	@Transactional
	public void delete(Long roleId) {
		roleObjRepo.deleteByRoleId(roleId);
		roleRepo.delete(roleId);
	}

	@Override
	public SysRole loadData(Long roleId) {
		return roleRepo.findOne(roleId);
	}

	@Override
	public String objs(Long id, String objType) {
		StringBuilder objIds = new StringBuilder();
		List<SysRoleObj> objs = roleObjRepo.findByRoleIdAndObjType(id,objType);
		if(objs!=null&&!objs.isEmpty()){
			for(SysRoleObj obj:objs){
				if(objIds.length()==0){
					objIds.append(obj.getObjId());
				}else{
					objIds.append(",").append(obj.getObjId());
				}
			}
		}
		return objIds.toString();
	}

	@Override
	@Transactional
	public void objsSave(Long roleId,String objIds,String objNames, String objType) {
		roleObjRepo.deleteByRoleIdAndObjType(roleId,objType);
		String[] objIdArray = objIds.split(",");
		String[] objNameArray = objNames.split(",");
		List<SysRoleObj> roleObjs = new ArrayList<SysRoleObj>();
		for(int i=0;i<objIdArray.length;i++){
			SysRoleObj roleObj = new SysRoleObj();
			roleObj.setObjId(G.l(objIdArray[i]));
			roleObj.setObjName(objNameArray[i]);
			roleObj.setObjType(objType);
			roleObj.setRoleId(roleId);
			roleObjs.add(roleObj);
		}
		roleObjRepo.save(roleObjs);
	}

	@Override
	public void deleteObj(Long id) {
		roleObjRepo.delete(id);
	}

	@Override
	public List<SysRole> findAllRoles(SysUser user, List<SysOrg> orgList) {
		List<SysRole> sysRoleList = new ArrayList<SysRole>();
		initDistinctRoleList(sysRoleList, "U", user.getUserId());
		if (orgList != null && !orgList.isEmpty()) {
			for (SysOrg sysOrg : orgList) {
				initDistinctRoleList(sysRoleList, "G", sysOrg.getOrgId());
			}
		}

		return sysRoleList;
	}
	
	public void initDistinctRoleList(List<SysRole> sysRoleList, String objType, Long objId) {
		List<SysRoleObj> roleObjList = roleObjRepo.findByObjIdAndObjType(objId,objType);
		if (roleObjList != null && !roleObjList.isEmpty()) {
			for (SysRoleObj roleObj : roleObjList) {
				SysRole role = roleRepo.findOne(roleObj.getRoleId());
				if (!sysRoleList.contains(role)) {
					sysRoleList.add(role);
				}
			}
		}
	}

}
